#include "QRONode_P.h"

static void initializeNode(QRONode::Private *_P,QVariant var);
static void initializeChannel(QRONode::Private *_P);

void QRONode::Private::onConnectToHost(QString host,QVariant var)
{
    bool ret = m_node->connectToNode(host);

    m_register = m_node->acquire<RemoteRegistryReplica>();
    m_register->setParent(_Q);
    QObject::connect(m_register,&RemoteInterfaceReplica::stateChanged,[=](RemoteRegistryReplica::State now,RemoteInterfaceReplica::State old){
        if(RemoteRegistryReplica::Default == old && RemoteRegistryReplica::Valid == now)
        {
            initializeNode(this,var);
        }
    });
}

void QRONode::Private::unregisterChannel(){
    if(m_register)
    {
        m_register->unregisterChannel(m_channel->id());
    }
}

static void initializeNode(QRONode::Private *_P,QVariant var)
{
    auto ret = _P->m_register->registerChannel(var);
    QRemoteObjectPendingCallWatcher* watcher = new QRemoteObjectPendingCallWatcher(ret);
    QObject::connect(watcher,&QRemoteObjectPendingCallWatcher::finished,[=](){
        int channelId = ret.returnValue();

        if(channelId <= 0)
        {
            _P->m_register->deleteLater();
            emit _P->_Q->connectFailed();

            return;
        }

        auto channelName = ChannelShareName.arg(channelId);
        _P->m_channel = _P->m_node->acquire<RemoteInterfaceReplica>(channelName);

        _P->m_channel->setParent(_P->_Q);
        QObject::connect(_P->m_channel,&RemoteInterfaceReplica::stateChanged,[=](RemoteInterfaceReplica::State now,RemoteInterfaceReplica::State old){
            if(RemoteInterfaceReplica::Default == old && RemoteInterfaceReplica::Valid == now)
            {
                initializeChannel(_P);
            }
        });

        delete watcher;
    });

}

static void initializeChannel(QRONode::Private *_P)
{
    QObject::connect(_P->m_channel,&RemoteInterfaceReplica::clientCall,[=](int id, int method, QVariantList param,int sync,bool isSource){
        _P->onClientCall(id,method,param,sync,isSource);
    });
    QObject::connect(_P->m_channel,&RemoteInterfaceReplica::propertyUpdate,[=](QByteArray data){
        _P->onPropertyUpdate(data);
    });
    QObject::connect(_P->m_channel,&RemoteInterfaceReplica::parentUpdate,[=](int target,int parent){
        _P->onParentUpdate(target,parent);
    });
    QObject::connect(_P->m_channel,&RemoteInterfaceReplica::newObject,[=](QByteArray data){
        _P->onNewObject(data);
    });
    QObject::connect(_P->m_channel,&RemoteInterfaceReplica::removedObject,[=](QList<quint32> list){
        _P->onHostObjectRemoved(list);
    });
    QObject::connect(_P->m_channel,&RemoteInterfaceReplica::serverCallFinished,[=](int sync,QVariant res,bool success){
        _P->onServerCallFinished(sync,res,success);
    });
    QObject::connect(_P->m_channel,&RemoteInterfaceReplica::ownedObjsChanged,[=](){
        _P->onOwnedObjectChanged();
    });
    auto ret = _P->m_channel->initialUpdate();
    auto watcher = new QRemoteObjectPendingCallWatcher(ret);
    QObject::connect(watcher,&QRemoteObjectPendingCallWatcher::finished,[=](){

        watcher->deleteLater();

        QByteArray b_data = ret.returnValue();
        auto data = uncompressVariant(b_data).toMap();

        QVariant objPacket = data["obj"];
        QVariant parentPacket = data["parent"];
        QVariant propPacket = data["prop"];

        QList<QObject*> linked;
        _P->handleObjPacket(objPacket,linked);
        _P->handleParentPacket(parentPacket);
        _P->handlePropPacket(propPacket);

        for(auto i:linked)
        {
            emit _P->_Q->objectLinked(i);
        }

        emit _P->_Q->connected();
    });
}
